package org.niux.AutoLoginQQ.common;

import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.niux.AutoLoginQQ.operate.LoginTask;
import org.niux.AutoLoginQQ.operate.LogoutTask;
import org.niux.AutoLoginQQ.operate.SendPollTask;

/**
 * 线程池 创建线程池，销毁线程池，添加新任务
 * 
 * @author obullxl
 */
public final class ThreadPoolManager {
	private static Logger log = Logger.getLogger(ThreadPoolManager.class);

	/* 单例 */
	private static ThreadPoolManager instance = null;

	public static final int SYSTEM_BUSY_TASK_COUNT = 150;
	/* 默认池中线程数 */
	public static int worker_num = 300;
	/* 已经处理的任务数 */
	private static int taskCounter = 0;

	private static int logoutTaskCounter = 0;

	private static int sendPollTaskCounter = 0;

	public static boolean systemIsBusy = false;

	private static List<LoginTask> taskQueue = Collections
			.synchronizedList(new LinkedList<LoginTask>());

	private static List<LogoutTask> logoutTaskQueue = Collections
			.synchronizedList(new LinkedList<LogoutTask>());
	
	private static List<SendPollTask> sendPollTaskQueue = Collections
			.synchronizedList(new LinkedList<SendPollTask>());
	/* 池中的所有线程 */
	public LoginPoolWorker[] loginWorkers;
	public LogoutPoolWorker[] logoutWorkers;
	public SendPollPoolWorker[] sendPollWorkers;

	private ThreadPoolManager() {
		loginWorkers = new LoginPoolWorker[300];
		logoutWorkers = new LogoutPoolWorker[300];
		sendPollWorkers = new SendPollPoolWorker[300];
		
		log.debug("创建登录线程池，默认线程数300");
		for (int i = 0; i < loginWorkers.length; i++) {
			loginWorkers[i] = new LoginPoolWorker(i);
		}
		
		log.debug("创建退出线程池，默认线程数300");
		for (int i = 0; i < logoutWorkers.length; i++) {
			logoutWorkers[i] = new LogoutPoolWorker(i);
		}
		
		log.debug("创建发送心跳包线程池，默认线程数300");
		for (int i = 0; i < sendPollWorkers.length; i++) {
			sendPollWorkers[i] = new SendPollPoolWorker(i);
		}
	}

	private ThreadPoolManager(int pool_worker_num) {
		worker_num = pool_worker_num;
		loginWorkers = new LoginPoolWorker[worker_num];
		logoutWorkers = new LogoutPoolWorker[worker_num];
		sendPollWorkers = new SendPollPoolWorker[worker_num];
		
		log.debug("创建登录线程池，默认线程数" + pool_worker_num);
		for (int i = 0; i < loginWorkers.length; i++) {
			loginWorkers[i] = new LoginPoolWorker(i);
		}
		
		log.debug("创建退出线程池，默认线程数" + pool_worker_num);
		for (int i = 0; i < logoutWorkers.length; i++) {
			logoutWorkers[i] = new LogoutPoolWorker(i);
		}
		
		log.debug("创建发送心跳包线程池，默认线程数" + pool_worker_num);
		for (int i = 0; i < sendPollWorkers.length; i++) {
			sendPollWorkers[i] = new SendPollPoolWorker(i);
		}
	}

	public static synchronized ThreadPoolManager getInstance(int pool_worker_num) {
		if (instance == null)
			return new ThreadPoolManager(pool_worker_num);
		return instance;
	}

	/**
	 * 增加新的任务 每增加一个新任务，都要唤醒任务队列
	 * 
	 * @param newTask
	 */
	public void addTask(LoginTask newTask) {
		synchronized (taskQueue) {
			newTask.setTaskId(++taskCounter);
			newTask.setSubmitTime(new Date());
			taskQueue.add(newTask);
			/* 唤醒队列, 开始执行 */
			taskQueue.notifyAll();
		}
		log.debug("添加登录线程任务");
	}

	/**
	 * 增加新的任务 每增加一个新任务，都要唤醒任务队列
	 * 
	 * @param newTask
	 */
	public void addLogoutTask(LogoutTask newTask) {
		synchronized (logoutTaskQueue) {
			newTask.setTaskId(++logoutTaskCounter);
			newTask.setSubmitTime(new Date());
			logoutTaskQueue.add(newTask);
			/* 唤醒队列, 开始执行 */
			logoutTaskQueue.notifyAll();
		}
		log.debug("添加退出线程任务");
	}

	/**
	 * 增加新的任务 每增加一个新任务，都要唤醒任务队列
	 * 
	 * @param newTask
	 */
	public void addSendPollTask(SendPollTask newTask) {
		synchronized (sendPollTaskQueue) {
			newTask.setTaskId(++sendPollTaskCounter);
			newTask.setSubmitTime(new Date());
			sendPollTaskQueue.add(newTask);
			/* 唤醒队列, 开始执行 */
			sendPollTaskQueue.notifyAll();
		}
		log.debug("添加发送心跳包线程任务");
	}

	/**
	 * 批量增加新任务
	 * 
	 * @param taskes
	 */
	public void batchAddTask(LoginTask[] taskes) {
		if (taskes == null || taskes.length == 0) {
			return;
		}
		synchronized (taskQueue) {
			for (int i = 0; i < taskes.length; i++) {
				if (taskes[i] == null) {
					continue;
				}
				taskes[i].setTaskId(++taskCounter);
				taskes[i].setSubmitTime(new Date());
				taskQueue.add(taskes[i]);
			}
			/* 唤醒队列, 开始执行 */
			taskQueue.notifyAll();
		}
		for (int i = 0; i < taskes.length; i++) {
			if (taskes[i] == null) {
				continue;
			}
		}
	}

	/**
	 * 线程池信息
	 * 
	 * @return
	 */
	public void getInfo() {
		log.debug("线程池大小:" + worker_num);
		int loginWaiting = 0;
		int loginRunning = 0;
		for (int i = 0; i < loginWorkers.length; i++) {
			if (loginWorkers[i].isWaiting()) {
				loginWaiting++;
			} else {
				loginRunning++;
			}
		}
		log.debug(loginRunning + "条登录线程正在运行，" + loginWaiting + "条登录线程在等待");
		
		int logoutWaiting = 0;
		int logoutRunning = 0;
		for (int i = 0; i < logoutWorkers.length; i++) {
			if (logoutWorkers[i].isWaiting()) {
				logoutWaiting++;
			} else {
				logoutRunning++;
			}
		}
		log.debug(logoutRunning + "条退出线程正在运行，" + logoutWaiting + "条退出线程在等待");
		
		int sendPollWaiting = 0;
		int sendPollRunning = 0;
		for (int i = 0; i < sendPollWorkers.length; i++) {
			if (sendPollWorkers[i].isWaiting()) {
				sendPollWaiting++;
			} else {
				sendPollRunning++;
			}
		}
		log.debug(sendPollRunning + "条发送心跳包线程正在运行，" + sendPollWaiting + "条发送心跳包线程在等待");
	}

	/**
	 * 销毁线程池
	 */
	public synchronized void destroy() {
		for (int i = 0; i < worker_num; i++) {
			loginWorkers[i].stopWorker();
			loginWorkers[i] = null;
			
			logoutWorkers[i].stopWorker();
			logoutWorkers[i] = null;
			
			sendPollWorkers[i].stopWorker();
			sendPollWorkers[i] = null;
		}
		taskQueue.clear();
		logoutTaskQueue.clear();
		sendPollTaskQueue.clear();
	}

	/**
	 * 池中工作线程
	 * 
	 * @author obullxl
	 */
	private class LoginPoolWorker extends Thread {
		/* 该工作线程是否有效 */
		private boolean isRunning = true;
		/* 该工作线程是否可以执行新任务 */
		private boolean isWaiting = true;

		public LoginPoolWorker(int index) {
			start();
		}

		public void stopWorker() {
			this.isRunning = false;
		}

		public boolean isWaiting() {
			return this.isWaiting;
		}

		/**
		 * 循环执行任务 这也许是线程池的关键所在
		 */
		public void run() {
			while (isRunning) {
				LoginTask r = null;

				// 登录任务
				synchronized (taskQueue) {
					while (taskQueue.isEmpty()) {
						try {
							/* 任务队列为空，则等待有新任务加入从而被唤醒 */
							taskQueue.wait(20);
						} catch (InterruptedException ie) {
							log.error(ie);
						}
					}
					/* 取出任务执行 */
					r = (LoginTask) taskQueue.remove(0);
				}
				if (r != null) {
					isWaiting = false;
					try {
						new Thread(r).start();
					} catch (Exception e) {
						e.printStackTrace();
						log.error(e);
					}
					isWaiting = true;
					r = null;
				}
			}
		}
	}

	/**
	 * 池中工作线程
	 * 
	 * @author obullxl
	 */
	private class LogoutPoolWorker extends Thread {
		/* 该工作线程是否有效 */
		private boolean isRunning = true;
		/* 该工作线程是否可以执行新任务 */
		private boolean isWaiting = true;

		public LogoutPoolWorker(int index) {
			start();
		}

		public void stopWorker() {
			this.isRunning = false;
		}

		public boolean isWaiting() {
			return this.isWaiting;
		}

		/**
		 * 循环执行任务 这也许是线程池的关键所在
		 */
		public void run() {
			while (isRunning) {
				LogoutTask logoutTask = null;

				// 退出登录
				synchronized (logoutTaskQueue) {
					while (logoutTaskQueue.isEmpty()) {
						try {
							/* 任务队列为空，则等待有新任务加入从而被唤醒 */
							logoutTaskQueue.wait(20);
						} catch (InterruptedException ie) {
							log.error(ie);
						}
					}
					/* 取出任务执行 */
					logoutTask = (LogoutTask) logoutTaskQueue.remove(0);
				}
				if (logoutTask != null) {
					isWaiting = false;
					try {
						new Thread(logoutTask).start();
					} catch (Exception e) {
						e.printStackTrace();
						log.error(e);
					}
					isWaiting = true;
					logoutTask = null;
				}
			}
		}
	}
	
	/**
	 * 池中工作线程
	 * 
	 * @author obullxl
	 */
	private class SendPollPoolWorker extends Thread {
		/* 该工作线程是否有效 */
		private boolean isRunning = true;
		/* 该工作线程是否可以执行新任务 */
		private boolean isWaiting = true;

		public SendPollPoolWorker(int index) {
			start();
		}

		public void stopWorker() {
			this.isRunning = false;
		}

		public boolean isWaiting() {
			return this.isWaiting;
		}

		/**
		 * 循环执行任务 这也许是线程池的关键所在
		 */
		public void run() {
			while (isRunning) {
				SendPollTask sendPollTask = null;

				// 发送心跳包任务
				synchronized (sendPollTaskQueue) {
					while (sendPollTaskQueue.isEmpty()) {
						try {
							/* 任务队列为空，则等待有新任务加入从而被唤醒 */
							sendPollTaskQueue.wait(20);
						} catch (InterruptedException ie) {
							log.error(ie);
						}
					}
					/* 取出任务执行 */
					sendPollTask = (SendPollTask) sendPollTaskQueue.remove(0);
				}
				if (sendPollTask != null) {
					isWaiting = false;
					try {
						log.debug("执行发送心跳包任务");
						new Thread(sendPollTask).start();
					} catch (Exception e) {
						e.printStackTrace();
						log.error(e);
					}
					isWaiting = true;
					sendPollTask = null;
				}
			}
		}
	}
}
